package com.woniuxy.zuul.filter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.woniuxy.common.DTO.ResponseResult;
import com.woniuxy.common.entity.Student;
import lombok.extern.slf4j.Slf4j;
import org.openjdk.jol.info.ClassLayout;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: linKe
 * @Date: 2022/1/24 10:51
 * @FileName: LoginZuulFilter
 * @version: 1.0
 * @Description: ZuulFilter 实现
 * 使用日志方式记录异常
 */
@Slf4j
@Component
public class LoginZuulFilter extends ZuulFilter {
    /**
     * 拦截类型：拦截器在什么时候执行
     * 按类型对过滤器进行分类。
     * Zuul 中的标准类型是“pre”用于路由前过滤，
     * “route”用于路由到源，“post”用于路由后过滤器，“error”用于错误处理。
     * 我们还支持静态响应的“静态”类型，请参阅 StaticResponseFilter。
     * 通过调用 FilterProcessor.runFilters(type) 创建或添加并运行任何 filterType
     *
     * @return 结果
     */
    @Override
    public String filterType() {
        // 在身份认证之前执行
        return "pre";
    }

    /**
     * 过滤顺序设置
     * 还必须为过滤器定义 filterOrder()。
     * 如果优先级对过滤器不重要，则过滤器可能具有相同的 filterOrder
     * @return  结果
     *
     */
    @Override
    public int filterOrder() {

        return 0;
    }

    /**
     * 应用过滤  此方法的“真”返回意味着应该调用 run() 方法
     * 是否执行run（）
     *
     * @return 结果
     */
    @Override
    public boolean shouldFilter() {
        // 获取请求上下文环境 对象
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();
        String name = request.getParameter("name");
        if (!StringUtils.isEmpty(name)) {
            // 处理带有*布局信息的类数据。 无垃圾稳态日志处理 看不懂
           ///  log.info("内部信息：[{}]", ClassLayout.parseInstance(pojo).toPrintable());
            log.info("认证确认信息：[{}]", "有name不拦截，直接放行");
            return false;
        }


        return true;
    }

    /**
     * 如果 shouldFilter() 为真，将调用此方法。
     * 这个方法是一个ZuulFilter的核心方法
     * 真正拦截器执行的方法
     * @return  结果
     * @throws ZuulException zuul 异常
     */
    @Override
    public Object run() throws ZuulException {
        log.info("错误信息：[{}]", "没有name，执行拦截方法，判断有没有token");
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();
        String token = request.getParameter("token");

        if (StringUtils.isEmpty(token)) {
            log.info("错误信息：[{}]", "没有token，拦截，不能访问");
            // 响应
            currentContext.setSendZuulResponse(false);
            // 设置响应状态码
            currentContext.setResponseStatusCode(500);
            try {
                // 响应处理
                currentContext.setResponseBody(new ObjectMapper().writeValueAsString(
                        new ResponseResult<String>(401,"authentication","login first")
                ));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }else {
            log.info("认证成功信息：[{}]", "有token，放行");
        }


        return null;
    }
}
